<?php


namespace App\Core\Database;

use BadMethodCallException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Redis;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Eloquent\RelationNotFoundException;

class EloquentBuilder extends Builder
{
    public function withoutCache()
    {
        $this->model->withoutCache();

        return $this;
    }

    public function withoutRelaion()
    {
        $this->model->withoutRelaion();

        return $this;
    }

    /**
     * Get the relation instance for the given relation name.
     *
     * @param  string  $name
     * @return \Illuminate\Database\Eloquent\Relations\Relation
     */
    public function getRelation($name)
    {
        // We want to run a relationship query without any constrains so that we will
        // not have to remove these where clauses manually which gets really hacky
        // and error prone. We don't want constraints because we add eager ones.
        $relation = Relation::noConstraints(function () use ($name) {
            try {
                return $this->getModel()->newInstance()->$name();
            } catch (BadMethodCallException $e) {
                throw RelationNotFoundException::make($this->getModel(), $name);
            }
        });


        // 如果with的关联不需要走缓存，关闭related的模型缓存
        if(! $this->model->isRelationsCacheable() &&
            property_exists($relation->getRelated(), 'isCacheable') &&
            $relation->getRelated()->isCacheable() == false
        ) {
            $relation->getRelated()->withoutCache();
        }

        $nested = $this->relationsNestedUnder($name);

        // If there are nested relationships set on the query, we will put those onto
        // the query instances so that they can be handled after this relationship
        // is loaded. In this way they will all trickle down as they are loaded.
        if (count($nested) > 0) {
            $relation->getQuery()->with($nested);
        }

        return $relation;
    }

    /**
     * Rewrite the relation qeury for model cache
     *
     * @param [type] $relation
     * @return void
     */
    public function resetRelationBuilder(Relation $relation)
    {

        $builder = $relation->getQuery();

        $query = $builder->getQuery();

        $newQuery = new QueryBuilder(
            $query->connection, $query->grammar, $query->processor, $builder->getModel()
        );

        $newQuery->from($builder->getModel()->getTable());

        $builder->setQuery($newQuery);
    }
}
